package com.we823.project.core.web.security.filter;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.we823.project.core.web.WebConstants;
import com.we823.project.model.UserModel;
import com.we823.project.repository.service.UserService;
import com.we823.project.repository.service.sys.LogService;
import com.we823.project.repository.service.sys.RoleService;
import com.we823.utils.web.RequestUtil;

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {

	private Logger logger = LoggerFactory
			.getLogger(CustomFormAuthenticationFilter.class);

	private List<String> blackUrls = new ArrayList<String>();
	private String customUserCookie = "materialCookie";
	private String customRememberMe = "customRememberMe";

	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private LogService logService;

	@Override
	public boolean onPreHandle(ServletRequest request,
			ServletResponse response, Object mappedValue) throws Exception {
		logger.debug("onPreHandle...");

		boolean isAccessAllowed = isAccessAllowed(request, response,
				mappedValue);

		boolean isLoginRequest = isLoginRequest(request, response);

		logger.debug("onPreHandle isAccessAllowed:{} ,isLoginRequest:{}", isAccessAllowed,
				isLoginRequest);
		// 登录跳转
		if (isAccessAllowed && isLoginRequest) {
			logger.debug("onPreHandle issueSucessReidrect...");
			try {
				issueSuccessRedirect(request, response);
			}catch(Exception ex) {
				logger.debug("issueSuccessRedirect error:{}",ex);
			}
			return false;
		}
		boolean onAccessDenied = onAccessDenied(request, response);
		logger.debug("onPreHandle isAccessAllowed:{} ,onAccessDenied:{}", isAccessAllowed,
				onAccessDenied);
		return isAccessAllowed || onAccessDenied;
	}

	@Override
	protected boolean executeLogin(ServletRequest request,
			ServletResponse response) throws Exception {
		logger.debug("executeLogin...");
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		boolean isRememberme = RequestUtil.getBooleanValue(httpServletRequest, "rememberMe");
		Cookie userCookie = new Cookie(customUserCookie, getUsername(request));
		Cookie rememberMeCookie = new Cookie(customRememberMe, isRememberme+"");
		userCookie.setMaxAge(3600);
		rememberMeCookie.setMaxAge(3600);
		
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		httpServletResponse.addCookie(userCookie);
		httpServletResponse.addCookie(rememberMeCookie);
		
		return super.executeLogin(request, response);
	}
	

	@Override
	protected void setFailureAttribute(ServletRequest request,
			AuthenticationException ae) {
		request.setAttribute(getFailureKeyAttribute(), ae);
	}

	@Override
	public String getSuccessUrl() {
		
		return super.getSuccessUrl();
	}

	@Override
	protected boolean onLoginSuccess(AuthenticationToken token,
			Subject subject, ServletRequest request, ServletResponse response)
			throws Exception {
		String username = (String) token.getPrincipal();
		logger.debug("onLoginSuccess:{}", username);

		logger.debug("set user to session...");
		Session session = subject.getSession();
		session.setAttribute("logining", 1);
		session.setAttribute(WebConstants.USERNAME, token.getPrincipal());
		
		UserModel userModel = userService.findByUsername(username);
		if (userModel != null) {
			session.setAttribute(WebConstants.CURRENT_USER, userModel);
		}
		logger.debug("set user to session end...");
		
		logService.loginSuccess(token.getPrincipal().toString());

		return super.onLoginSuccess(token, subject, request, response);
	}

	@Override
	protected boolean onLoginFailure(AuthenticationToken token,
			AuthenticationException e, ServletRequest request,
			ServletResponse response) {
		if (token != null) {
			logService.loginFailure(token.getPrincipal().toString());
		} else {
			logService.loginFailure("未知用户名");
		}
		return super.onLoginFailure(token, e, request, response);
	}

	@Override
	protected void issueSuccessRedirect(ServletRequest request,
			ServletResponse response) throws Exception {
		logger.debug("issueSuccessRedirect....");
		String successUrl = null;
		SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request);
		if (savedRequest != null) {
			logger.debug("savedRequest isnot null");
			successUrl = savedRequest.getRequestUrl();
			logger.debug("successUrl:{}",successUrl);
			List<String> newBlackUrlList = new ArrayList<String>();
			if (blackUrls != null && blackUrls.size() > 0) {
				HttpServletRequest httpServletRequest = (HttpServletRequest) request;
				for (String blackUrl : blackUrls) {
					if(blackUrl.equals("/")) {
						blackUrl = httpServletRequest.getContextPath();
					}else {
						blackUrl = httpServletRequest.getContextPath()
								+ "/" + blackUrl;
					}
					
					newBlackUrlList.add(blackUrl);
					logger.debug("blackUrl:{}",blackUrl);
				}
			}
			if (newBlackUrlList.contains(successUrl)) {
				successUrl = getSuccessUrl();
				logger.debug("contain blackUrl and getSuccessUrl:{}",successUrl);
				WebUtils.issueRedirect(request, response, successUrl);
			} else {
				logger.debug("not contain blackUrl and change to confirm successUrl");
				if(StringUtils.isBlank(successUrl)) {
					logger.debug("successUrl is null and get super.issueSuccessRedirect...");
				    super.issueSuccessRedirect(request, response);
				}else {
					logger.debug("successUrl is not null and use WebUtils.issueRedirect..");
					
					WebUtils.issueRedirect(request, response, successUrl, null, false);
				}
			}
		}else {
			logger.debug("savedRequest isnull and get super.issueSuccessRedirect");
			super.issueSuccessRedirect(request, response);
		}
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public RoleService getRoleService() {
		return roleService;
	}

	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}

	public LogService getLogService() {
		return logService;
	}

	public void setLogService(LogService logService) {
		this.logService = logService;
	}

	public List<String> getBlackUrls() {
		return blackUrls;
	}

	public void setBlackUrls(List<String> blackUrls) {
		this.blackUrls = blackUrls;
	}

	public String getCustomUserCookie() {
		return customUserCookie;
	}

	public void setCustomUserCookie(String customUserCookie) {
		this.customUserCookie = customUserCookie;
	}

	public String getCustomRememberMe() {
		return customRememberMe;
	}

	public void setCustomRememberMe(String customRememberMe) {
		this.customRememberMe = customRememberMe;
	}
	
}
